package com.lingjtx.common.core.util;

import com.lingjtx.common.core.RedisOptions;
import com.lingjtx.common.core.algorithm.Algorithm;
import com.lingjtx.common.core.constant.RedisConfig;

import java.util.Objects;

/**
 * 生成激活链接，扫码完成后续业务
 */
public class LinkGenerator {

    private String link;

    public LinkGenerator(String link) {
        this.link = link;
    }

    public static Builder init() {
        return new LinkGenerator.Builder();
    }

    public String generator() {
        return this.link;
    }

    public static boolean valid(String key, RedisOptions redisOptions) {
        Integer count = (Integer) redisOptions.hmGet(key, RedisConfig.HASHKEY_VERIFY_LINK_COUNT);
        Long res = redisOptions.hmIncrement(key, RedisConfig.HASHKEY_VERIFY_LINK_INCREMENT, 1);
        if (count != null) {
            return res.intValue() <= count;
        }
        return false;
    }

    public static Object getData(String key, RedisOptions redisOptions) {
        return redisOptions.hmGet(key, RedisConfig.HASHKEY_VERIFY_LINK_DATA);
    }

    private void save(LinkGenerator.Builder builder) {
        builder.redisOptions.hmPut(builder.algorithm, RedisConfig.HASHKEY_VERIFY_LINK_DATA, builder.data);
        builder.redisOptions.hmPut(builder.algorithm, RedisConfig.HASHKEY_VERIFY_LINK_COUNT, builder.checks);
        builder.redisOptions.expire(builder.algorithm, builder.expire);
    }

    public static final class Builder {
        private Long expire = RedisConfig.TIMEOUT_LINK_ACTIVATE;

        private Long checks = Long.MAX_VALUE;

        private LinkType type = LinkType.IDENTITY;

        private String algorithm = Algorithm.UUID.toString();

        private String baseurl;

        private String uri = "";

        private LinkGeneratorHandler linkGeneratorHandler;

        private RedisOptions redisOptions;

        private Object data;

        public LinkGenerator.Builder setExpire(Long expire) {
            this.expire = expire;
            return this;
        }

        public LinkGenerator.Builder setChecks(Long checks) {
            this.checks = checks;
            return this;
        }

        public LinkGenerator.Builder setLinkType(LinkType type) {
            this.type = type;
            return this;
        }

        public LinkGenerator.Builder setAlgorithm(Algorithm algorithm) {
            this.algorithm = algorithm.toString();
            return this;
        }

        public LinkGenerator.Builder setBaseurl(String baseurl) {
            Objects.requireNonNull(baseurl, "baseurl is null");
            this.baseurl = baseurl;
            return this;
        }

        public LinkGenerator.Builder setUri(String uri) {
            this.uri = uri;
            return this;
        }

        public LinkGenerator.Builder setLinkGeneratorHandler(LinkGeneratorHandler linkGeneratorHandler) {
            Objects.requireNonNull(linkGeneratorHandler, "linkGeneratorHandler is null");
            this.linkGeneratorHandler = linkGeneratorHandler;
            return this;
        }

        public LinkGenerator.Builder setRedisOptions(RedisOptions redisOptions) {
            Objects.requireNonNull(linkGeneratorHandler, "redisOptions is null");
            this.redisOptions = redisOptions;
            return this;
        }

        public LinkGenerator.Builder setData(Object data) {
            this.data = data;
            return this;
        }

        public LinkGenerator build() {
            LinkGenerator generator = new LinkGenerator(this.linkGeneratorHandler.generator(this));
            generator.save(this);
            return generator;
        }

    }

    /**
     * 链接参数字段
     * 比如：http://xxx.com/xxx?identity=Algorithm
     */
    public enum LinkType {
        IDENTITY("identity"),

        UID("uid"),

        KEY("key"),

        INVITE("invite"),

        TOKEN("token");

        private String value;

        LinkType(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public static LinkType of(String name) {
            for (LinkType linkType : LinkType.values()) {
                if (Objects.equals(linkType.toString(), name)) {
                    return linkType;
                }
            }
            return null;
        }

        @Override
        public String toString() {
            return this.getValue();
        }
    }

    public static class RestfulPolicy implements LinkGeneratorHandler {


        @Override
        public String generator(Builder builder) {
            if (builder == null) {
                return null;
            }
            return String.format("%s%s/%s", builder.baseurl, builder.uri, builder.algorithm);
        }
    }

    public static class NonRestfulPolicy implements LinkGeneratorHandler {

        @Override
        public String generator(Builder builder) {
            if (builder == null) {
                return null;
            }
            return String.format("%s%s?%s=%s", builder.baseurl, builder.uri, builder.type, builder.algorithm);
        }
    }
}
